#pragma once

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<cstring>
#include<cstdlib>
#include<pthread.h>
#include"Log.hpp"
#include<unistd.h>

namespace wyl
{
    #define BLOCK 5
    
    class TcpServer
    {
    private:
        int sock_;
        int port_;
        static TcpServer* svr_;

        TcpServer(int port): port_(port) , sock_(-1)
        {}
        TcpServer(const TcpServer& s){}
        public:
        ~TcpServer(){
            close(sock_);
        }

        //获取套接字
        void Scoket()
        {
            sock_ = socket(AF_INET,SOCK_STREAM,0);
            if(sock_ < 0)
            {
                //日志
                LOG(FATAL,"socket create... error");
                exit(2);
            }
            LOG(INFO,"socket create... success");
            //地址复用
            int opt = 1;
            setsockopt(sock_,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
        }
        //绑定
        void Bind()
        {
            struct sockaddr_in local;
            memset(&local,0,sizeof(local));
            local.sin_port = htons(port_);
            local.sin_family = AF_INET;
            local.sin_addr.s_addr = INADDR_ANY;
            if(bind(sock_,(struct sockaddr*)&local,sizeof(local)) < 0)
            {
                //日志
                LOG(FATAL,"socket bind... error");
                exit(3);
            }
             LOG(INFO,"socket bind... success");
        }
        //监听
        void Listen()
        {
            if(listen(sock_,BLOCK) < 0)
            {
                //日志
                LOG(FATAL,"socket listen... error");
                exit(4);
            }
            LOG(INFO,"socket lsiten... success");
        }
        //初始化服务器
        void InitServer()
        {
            Scoket();
            Bind();
            Listen();
            LOG(INFO,"tcp server init... success");
        }

        //获取单例对象
        static TcpServer* getinstance(int port)
        {
            //定义一把静态锁
            static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
            //对象未被创建时创建对象
            if(svr_ == nullptr) 
            {
                //临界资源，需要加锁
                pthread_mutex_lock(&mutex);
                if(svr_ == nullptr)
                {
                    //创建服务器对象
                    svr_ = new TcpServer(port);
                    svr_ ->InitServer();
                }
                pthread_mutex_unlock(&mutex); //解锁
            }
            return svr_;
        }

        //获取sock
        int GetSock()
        {
            return sock_;
        }
    };
    TcpServer* TcpServer::svr_ = nullptr;
}